package cli

import (
	"5title_gin/global"
	"5title_gin/internal/model/business/orders"
	"5title_gin/internal/model/system/dept"
	"5title_gin/internal/model/system/menu"
	"5title_gin/internal/model/system/roles"
	"5title_gin/internal/model/user"
	"go.uber.org/zap"
	"os"
	"strings"
)

// modelFactory 定义一个函数类型，用于创建模型实例
type modelFactory func() interface{}

// modelMap 映射表：模型名称 -> 创建模型实例的函数
var modelMap = map[string]modelFactory{
	"user.UserModel":  func() interface{} { return &user.UserModel{} },
	"sys.SysDept":     func() interface{} { return &dept.SysDept{} },
	"sys.SysMenu":     func() interface{} { return &menu.SysMenu{} },
	"sys.SysRoles":    func() interface{} { return &roles.SysRoles{} },
	"sys.SysRoleUser": func() interface{} { return &roles.SysRoleUser{} },
	"sys.SysRoleMenu": func() interface{} { return &roles.SysRoleMenu{} },
	"svc.Order":       func() interface{} { return &orders.Orders{} },
}

func MigrateDB() {
	// 检查 global.DB 是否已初始化
	if global.DB == nil {
		zap.S().Error("数据库未初始化，请检查 global.DB 是否正确配置")
		os.Exit(1)
	}

	// 确定需要迁移的模型列表
	var modelsToMigrate []string
	if Options.MigrateModel == "" {
		// 如果未指定 -model，迁移所有模型
		zap.S().Infof("未指定模型，将迁移所有 %d 个模型", len(modelMap))
		for modelName := range modelMap {
			modelsToMigrate = append(modelsToMigrate, modelName)
		}
	} else {
		// 如果指定了 -model，按逗号分隔解析
		models := strings.Split(Options.MigrateModel, ",")
		for _, modelName := range models {
			modelName = strings.TrimSpace(modelName)
			if modelName == "" {
				continue
			}
			modelsToMigrate = append(modelsToMigrate, modelName)
		}
	}

	// 如果没有需要迁移的模型，打印支持的模型列表
	if len(modelsToMigrate) == 0 {
		zap.S().Error("没有有效的模型需要迁移")
		zap.S().Info("支持的模型：")
		for modelName := range modelMap {
			zap.S().Infof("- %s", modelName)
		}
		os.Exit(1)
	}

	// 开始迁移
	zap.S().Infof("开始迁移 %d 个模型", len(modelsToMigrate))

	// 记录失败的模型数量
	failedCount := 0

	// 遍历模型列表，执行迁移
	for _, modelName := range modelsToMigrate {
		// 查找模型对应的工厂函数
		factory, exists := modelMap[modelName]
		if !exists {
			zap.S().Errorf("不支持的模型：%s", modelName)
			zap.S().Info("支持的模型：")
			for name := range modelMap {
				zap.S().Infof("- %s", name)
			}
			failedCount++
			continue
		}

		// 创建模型实例并执行迁移
		model := factory()
		err := global.DB.AutoMigrate(model)
		if err != nil {
			zap.S().Warnf("数据库迁移失败 %s: %s", modelName, err)
			failedCount++
			continue
		}
		zap.S().Infof("数据库迁移成功：%s", modelName)
	}

	// 如果所有模型都失败，打印错误并退出
	if failedCount == len(modelsToMigrate) && len(modelsToMigrate) > 0 {
		zap.S().Error("所有模型迁移均失败，请检查数据库配置或模型定义")
		os.Exit(1)
	}

	// 打印迁移总结
	zap.S().Infof("数据库迁移完成：成功 %d 个，失败 %d 个", len(modelsToMigrate)-failedCount, failedCount)
}
